package edu.hznu.retroSnakerPlanServer.service.imp;

import edu.hznu.retroSnakerPlanServer.entity.*;
import edu.hznu.retroSnakerPlanServer.service.FoodService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;

/**
 * create by Cliven on 2018-06-01 16:04
 *
 * @author Cliven
 * 实现了食物的增加修改查询等..
 */
public class FoodServiceImpl implements FoodService {

    private static final Logger log = LoggerFactory.getLogger(FoodServiceImpl.class);

    private GameContext ctx;
    private Random random;

    private void FoodServiceImpl() {
    }

    public FoodServiceImpl(GameContext ctx) {
        this.ctx = ctx;
        this.random = new Random();
    }

    /**
     * 批量删除游戏中的食物
     *
     * @param foods 需要除去的食物
     * @author Cliven
     * @since 2018-6-1 20:56:30
     */
    @Override
    public synchronized void removeFoods(List<Food> foods) {
        if (foods == null) {
            throw new IllegalArgumentException("Remove foods foods is null");
        }
        Food[][] foodMap = ctx.getFoods();
        Integer x = null, y = null;
        for (Food foodItem : foods) {
            x = foodItem.getX();
            y = foodItem.getY();
            foodMap[x][y] = null;
        }
    }

    /**
     * 通过区域信息获取区域内的食物
     *
     * @param area 区域
     * @return 区域内的所有食物
     * @author Cliven
     * @since 2018-6-1 20:36:02
     */
    @Override
    public synchronized List<Food> getFoodsByArea(Area area) {
        List<Food> res = new LinkedList<>();
        Food[][] foods = ctx.getFoods();
        area.sx = (area.sx < 0) ? 0 : area.sx;
        area.sy = (area.sy < 0) ? 0 : area.sy;
        area.ex = (area.ex > ctx.getWidth()) ? ctx.getWidth() : area.ex;
        area.ey = (area.ey > ctx.getHeight()) ? ctx.getHeight() : area.ey;
        for (int i = area.sx; i <= area.ex; i++) {
            for (int j = area.sy; j <= area.ey; j++) {
                if (foods[i][j] != null) {
                    res.add(foods[i][j]);
                }
            }
        }
        return res;
    }

    /**
     * 把整条蛇作为食物
     *
     * @param snake 蛇的节点
     * @return 生成食物信息
     * @author Cliven
     * @since 2018-06-01 16:19:30
     */
    @Override
    public synchronized List<Food> add(List<SnakeNode> snake) {
        List<Food> foods = new ArrayList<>(snake.size());
        for (SnakeNode node : snake) {
            foods.add(add(node));
        }
        return foods;
    }

    /**
     * 根据蛇节点生成食物
     *
     * @param node 蛇的节点
     * @return 生成食物信息
     * @author Cliven
     * @since 2018-06-01 16:19:06
     */
    @Override
    public synchronized Food add(SnakeNode node) {
        Integer x = node.getX();
        x = (x < 0 && x == 65535) ? 1 : x;
        x = x > ctx.getWidth() ? ctx.getWidth() : x;

        Integer y = node.getY();
        y = (y < 1 && y == 65535) ? 1 : y;
        y = y > ctx.getHeight() ? ctx.getHeight() : y;
        log.debug("add No.{} x: {} y:{}", ctx.getFoodCnt(),x, y);
        Food food = new Food()
                .setX(x)
                .setY(y)
                .setColorType(node.getColorType());

        Food[][] foods = ctx.getFoods();
        foods[x][y] = food;
        return foods[x][y];
    }

    /**
     * 随机生成一个食物
     *
     * @return 生成的食物信息
     * @author Cliven
     * @since 2018-6-1 16:04:16
     */
    @Override
    public synchronized Food create() {
        Integer maxFoodNumber = ctx.getMaxFoodNumber();
        Integer currentFoodNumber = ctx.getFoodCnt();
        // 超过最大食物总量则不再生成
        if (currentFoodNumber >= maxFoodNumber) {
            return null;
        }
        Integer x, y;
        Integer wid = ctx.getWidth();
        Integer hei = ctx.getHeight();
        Integer colorType = random.nextInt(ColorType.TYPE_NUMBER);
        Food[][] foodMap = ctx.getFoods();
        // 随机食物坐标
        do {
            x = 4 + random.nextInt(wid - 4 * 2);
            y = 4 + random.nextInt(hei - 4 * 2);
        } while (foodMap[x][y] != null);
        foodMap[x][y] = new Food()
                .setX(x)
                .setY(y)
                .setColorType(colorType);
        ctx.addFoodCnt();
        log.debug("create NO. {} food:{}", ctx.getFoodCnt(), foodMap[x][y].toString());
        return foodMap[x][y];
    }

    /**
     * 删除一个食物
     *
     * @param x 坐标x
     * @param y 坐标y
     * @return 被删除的食物信息
     * @author Cliven
     * @since 2018-06-01 14:15:42
     */
    @Override
    public synchronized Food remove(Integer x, Integer y) {
        Food[][] foods = ctx.getFoods();
        Food food = null;
        if (foods[x][y] != null) {
            food = foods[x][y];
            foods[x][y] = null;
            ctx.reduceFoodCnt();
        }
        return food;
    }

    /**
     * 查找食物
     *
     * @param x 坐标x
     * @param y 坐标y
     * @return 食物信息
     * @author Cliven
     * @since 2018-06-01 14:16:41
     */
    @Override
    public Food find(Integer x, Integer y) {
        return ctx.getFoods()[x][y];
    }

    /**
     * 更新食物信息
     *
     * @param food 修改原先的食物信息
     * @return 食物信息
     * @author Cliven
     * @since 2018-06-01 14:17:19
     */
    @Override
    public synchronized Food update(Food food) {
        Food[][] foods = ctx.getFoods();
        foods[food.getX()][food.getY()] = food;
        return foods[food.getX()][food.getY()];
    }
}
